namespace C1.Win.C1FlexGrid.Util.Styles
{
    using C1.Util;
    using C1.Win.C1FlexGrid.Util;
    using System;
    using System.Collections;
    using System.Drawing;
    using System.Runtime.CompilerServices;

    internal class StyleContext
    {
        protected Style _baseStyle;
        private static char[] _breakChars = new char[] { ' ', '\t', '-' };
        internal static Font _defaultFont = SystemInformation.DefaultFont;
        protected StringFormat _format = new StringFormat();
        protected static Brush _lightBrush = new SolidBrush(Color.LightGray);
        protected static Brush _shadowBrush = new SolidBrush(Color.DarkGray);
        internal Brush _skipBrush;
        protected Hashtable _styles = new Hashtable();
        protected Color _transparentColor = Color.Transparent;

        public event StyleEventHandler StyleChanged;

        public StyleContext()
        {
            this._baseStyle = new Style(this, "Base", null);
            this.SetBaseAttributes();
        }

        public Style AddStyle()
        {
            return this.AddStyle(null, (Style) null);
        }

        public Style AddStyle(string name)
        {
            return this.AddStyle(name, (Style) null);
        }

        public Style AddStyle(string name, Style parent)
        {
            if (name == null)
            {
                name = this.CreateUniqueStyleName();
            }
            Style style = new Style(this, name, parent);
            this._styles.Add(name, style);
            return style;
        }

        public Style AddStyle(string name, string parent)
        {
            return this.AddStyle(name, this.GetStyle(parent));
        }

        protected static string[] BreakLines(Graphics g, string text, Font font, RectangleF rc, StringFormat sf)
        {
            string[] strArray = text.Split(new char[] { '\n' });
            if ((sf.FormatFlags & StringFormatFlags.NoWrap) != 0)
            {
                return strArray;
            }
            ArrayList list = new ArrayList();
            for (int i = 0; i < strArray.Length; i++)
            {
                string line = strArray[i];
                do
                {
                    int length = FindBreak(g, line, font, rc.Width);
                    list.Add(line.Substring(0, length).TrimEnd(new char[0]));
                    line = line.Substring(length);
                }
                while (line.Length != 0);
            }
            return (string[]) list.ToArray(typeof(string));
        }

        public void Clear()
        {
            this._styles.Clear();
            this.NotifyChange(null);
        }

        public int Count()
        {
            return this._styles.Count;
        }

        protected virtual string CreateUniqueStyleName()
        {
            int num = 1;
            while (true)
            {
                string name = "Style" + num.ToString();
                if (!this.HasStyle(name))
                {
                    return name;
                }
                num++;
            }
        }

        private void DrawImage(Graphics g, Image img, Rectangle r)
        {
            CFGraphics.DrawImage(g, img, r, this.TransparentColor);
        }

        private void DrawImage(Graphics g, Image img, Rectangle rimg, Rectangle rsrc)
        {
            CFGraphics.DrawImage(g, img, rimg, rsrc, this.TransparentColor);
        }

        private void DrawString(Graphics g, string str, Font f, Brush b, Rectangle r, StringFormat sf)
        {
            if (((sf.FormatFlags & StringFormatFlags.NoWrap) != 0) && (str.IndexOf("\n") < 0))
            {
                CFGraphics.DrawString(g, str, f, b, r, sf);
            }
            else
            {
                Rectangle rectangle = r;
                SizeF empty = SizeF.Empty;
                StringAlignment lineAlignment = sf.LineAlignment;
                if (sf.LineAlignment != StringAlignment.Near)
                {
                    empty = MeasureString(g, str, f, rectangle.Width, sf);
                    int num = r.Height - ((int) empty.Height);
                    if (num > 0)
                    {
                        switch (sf.LineAlignment)
                        {
                            case StringAlignment.Center:
                                rectangle.Y = r.Y + (num / 2);
                                break;

                            case StringAlignment.Far:
                                rectangle.Y = r.Y + num;
                                break;
                        }
                    }
                    sf.LineAlignment = StringAlignment.Near;
                }
                rectangle.Height = (int) CFGraphics.MeasureString(g, "A", f, 0x3e8, sf).Height;
                empty = SizeF.Empty;
                foreach (string str2 in BreakLines(g, str, f, r, sf))
                {
                    CFGraphics.DrawString(g, str2, f, b, rectangle, sf);
                    rectangle.Offset(0, rectangle.Height);
                    if (rectangle.Y > r.Bottom)
                    {
                        break;
                    }
                }
                sf.LineAlignment = lineAlignment;
            }
        }

        protected static int FindBreak(Graphics g, string line, Font font, float width)
        {
            int num2;
            if ((line.Length == 0) || (g.MeasureString(line, font).Width <= width))
            {
                return line.Length;
            }
            int num = -1;
        Label_0025:
            num2 = line.IndexOfAny(_breakChars, num + 1);
            if (num2 < 0)
            {
                if (num > 0)
                {
                    return (num + 1);
                }
                if (g.MeasureString(line, font).Width > width)
                {
                    for (int i = line.Length - 1; i >= 1; i--)
                    {
                        if (g.MeasureString(line.Substring(0, i), font).Width <= width)
                        {
                            return i;
                        }
                    }
                }
                return line.Length;
            }
            if (g.MeasureString(line.Substring(0, num2 + 1), font).Width <= width)
            {
                num = num2;
                goto Label_0025;
            }
            if (num <= 0)
            {
                return (num2 + 1);
            }
            return (num + 1);
        }

        public Style GetBaseStyle()
        {
            return this._baseStyle;
        }

        public virtual Rectangle GetContentRectangle(Style s, Rectangle r)
        {
            Margins attribute = (Margins) s.GetAttribute("Margins");
            r = InnerRect(r, attribute);
            attribute = ((Border) s.GetAttribute("Border")).GetInsets();
            r = InnerRect(r, attribute);
            return r;
        }

        protected virtual StringAlignment GetGeneralAlignment(string s)
        {
            if (!Types.IsNumeric(s))
            {
                return StringAlignment.Near;
            }
            return StringAlignment.Far;
        }

        public virtual int GetHeight(Style s, Graphics g, int wid, string str, Image img)
        {
            Rectangle r = new Rectangle(0, 0, wid, 0);
            r = this.GetContentRectangle(s, r);
            Margins attribute = (Margins) s.GetAttribute("Padding");
            r = InnerRect(r, attribute);
            int num = -r.Height;
            wid = r.Width;
            int num2 = 0;
            if ((str != null) && (str.Length > 0))
            {
                this.UpdateStringFormat(s, str, false);
                Font f = (Font) s.GetAttribute("Font");
                num2 = ((int) MeasureString(g, str, f, wid, this._format).Height) + 1;
                num += num2;
            }
            if (img != null)
            {
                AlignImageEnum ai = (AlignImageEnum) s.GetAttribute("AlignImage");
                if (this.ImageOnTop(ai) || this.ImageOnBottom(ai))
                {
                    return (num + (img.Height + ((int) s.GetAttribute("Spacing"))));
                }
                if (!this.ImageOnLeft(ai) && !this.ImageOnRight(ai))
                {
                    return num;
                }
                if (img.Height > num2)
                {
                    num += img.Height - num2;
                }
            }
            return num;
        }

        public virtual Rectangle GetImageRectangle(Style s, Rectangle r, Image img)
        {
            Rectangle rectangle;
            int num;
            int num2;
            AlignImageEnum attribute = (AlignImageEnum) s.GetAttribute("AlignImage");
            switch (attribute)
            {
                case AlignImageEnum.Hide:
                case AlignImageEnum.Stretch:
                case AlignImageEnum.Tile:
                    return r;

                default:
                {
                    rectangle = r;
                    Size size = img.Size;
                    if (size.Width < rectangle.Width)
                    {
                        rectangle.Width = size.Width;
                    }
                    if (size.Height < rectangle.Height)
                    {
                        rectangle.Height = size.Height;
                    }
                    num = r.Height - rectangle.Height;
                    num2 = r.Width - rectangle.Width;
                    switch (attribute)
                    {
                        case AlignImageEnum.LeftTop:
                            return rectangle;

                        case AlignImageEnum.LeftCenter:
                            rectangle.Offset(0, num / 2);
                            return rectangle;

                        case AlignImageEnum.LeftBottom:
                            rectangle.Offset(0, num);
                            return rectangle;

                        case AlignImageEnum.CenterTop:
                            rectangle.Offset(num2 / 2, 0);
                            return rectangle;

                        case AlignImageEnum.CenterCenter:
                            rectangle.Offset(num2 / 2, num / 2);
                            return rectangle;

                        case AlignImageEnum.CenterBottom:
                            rectangle.Offset(num2 / 2, num);
                            return rectangle;

                        case AlignImageEnum.RightTop:
                            rectangle.Offset(num2, 0);
                            return rectangle;

                        case AlignImageEnum.RightCenter:
                            rectangle.Offset(num2, num / 2);
                            return rectangle;

                        case AlignImageEnum.RightBottom:
                            rectangle.Offset(num2, num);
                            return rectangle;

                        case AlignImageEnum.Scale:
                            rectangle = r;
                            if ((rectangle.Width * size.Height) <= (rectangle.Height * size.Width))
                            {
                                rectangle.Height = (rectangle.Width * size.Height) / size.Width;
                                break;
                            }
                            rectangle.Width = (rectangle.Height * size.Width) / size.Height;
                            break;
                    }
                    return rectangle;
                }
            }
            num = r.Height - rectangle.Height;
            num2 = r.Width - rectangle.Width;
            rectangle.Offset(num2 / 2, num / 2);
            return rectangle;
        }

        public Style GetStyle(string name)
        {
            if (((Style) this._styles[name]) == null)
            {
                throw new ArgumentException("Style '" + name + "' not defined");
            }
            return (Style) this._styles[name];
        }

        public ICollection GetStyles()
        {
            return this._styles.Values;
        }

        public virtual Rectangle GetTextRectangle(Style s, Rectangle r, Image img)
        {
            AlignImageEnum attribute = (AlignImageEnum) s.GetAttribute("AlignImage");
            if (((attribute != AlignImageEnum.Stretch) && (attribute != AlignImageEnum.Tile)) && (img != null))
            {
                int num = (int) s.GetAttribute("Spacing");
                int num2 = img.Width + num;
                int num3 = img.Height + num;
                if (this.ImageOnLeft(attribute))
                {
                    r.X += num2;
                    r.Width -= num2;
                    return r;
                }
                if (this.ImageOnRight(attribute))
                {
                    r.Width -= num2;
                    return r;
                }
                if (this.ImageOnTop(attribute))
                {
                    r.Y += num3;
                    r.Height -= num3;
                    return r;
                }
                if (this.ImageOnBottom(attribute))
                {
                    r.Height -= num3;
                }
            }
            return r;
        }

        public virtual int GetWidth(Style s, Graphics g, string str, Image img)
        {
            Rectangle empty = Rectangle.Empty;
            empty = this.GetContentRectangle(s, empty);
            Margins attribute = (Margins) s.GetAttribute("Padding");
            int num = -InnerRect(empty, attribute).Width;
            int num2 = 0;
            if ((str != null) && (str.Length > 0))
            {
                Font font = (Font) s.GetAttribute("Font");
                num2 = ((int) g.MeasureString(str, font).Width) + 1;
                num += num2;
            }
            if (img != null)
            {
                AlignImageEnum ai = (AlignImageEnum) s.GetAttribute("AlignImage");
                if (this.ImageOnLeft(ai) || this.ImageOnRight(ai))
                {
                    return (num + (img.Width + ((int) s.GetAttribute("Spacing"))));
                }
                if (!this.ImageOnTop(ai) && !this.ImageOnBottom(ai))
                {
                    return num;
                }
                if (img.Width > num2)
                {
                    num += img.Width - num2;
                }
            }
            return num;
        }

        public bool HasStyle(string name)
        {
            return this._styles.Contains(name);
        }

        protected virtual bool ImageOnBottom(AlignImageEnum ai)
        {
            return (ai == AlignImageEnum.CenterBottom);
        }

        protected virtual bool ImageOnLeft(AlignImageEnum ai)
        {
            switch (ai)
            {
                case AlignImageEnum.LeftTop:
                    return true;

                case AlignImageEnum.LeftCenter:
                    return true;

                case AlignImageEnum.LeftBottom:
                    return true;
            }
            return false;
        }

        protected virtual bool ImageOnRight(AlignImageEnum ai)
        {
            switch (ai)
            {
                case AlignImageEnum.RightTop:
                    return true;

                case AlignImageEnum.RightCenter:
                    return true;

                case AlignImageEnum.RightBottom:
                    return true;
            }
            return false;
        }

        protected virtual bool ImageOnTop(AlignImageEnum ai)
        {
            return (ai == AlignImageEnum.CenterTop);
        }

        public static Rectangle InnerRect(Rectangle r, Margins m)
        {
            r.X += m.Left;
            r.Y += m.Top;
            r.Width -= m.Left + m.Right;
            r.Height -= m.Top + m.Bottom;
            return r;
        }

        private static SizeF MeasureString(Graphics g, string str, Font f, int wid, StringFormat sf)
        {
            if (((sf.FormatFlags & StringFormatFlags.NoWrap) != 0) && (str.IndexOf("\n") < 0))
            {
                return CFGraphics.MeasureString(g, str, f, wid, sf);
            }
            SizeF ef = new SizeF(0f, 0f);
            RectangleF rc = new RectangleF(0f, 0f, (float) wid, 10000f);
            foreach (string str2 in BreakLines(g, str, f, rc, sf))
            {
                SizeF ef3 = CFGraphics.MeasureString(g, str2, f, wid, sf);
                ef.Height += ef3.Height;
                ef.Width = Math.Max(ef.Width, ef3.Width);
            }
            return ef;
        }

        public virtual void NotifyChange(Style s)
        {
            StyleEventArgs e = new StyleEventArgs(s);
            this.OnStyleChanged(e);
        }

        public virtual void OnStyleChanged(StyleEventArgs e)
        {
            if (this.StyleChanged != null)
            {
                this.StyleChanged(this, e);
            }
        }

        public void RemoveStyle(Style s)
        {
            Style parent = s.GetParent();
            foreach (Style style2 in this.GetStyles())
            {
                if (style2.GetParent() == s)
                {
                    style2.SetParent(parent);
                }
            }
            this._styles.Remove(s.GetName());
            this.NotifyChange(null);
        }

        public void RemoveStyle(string name)
        {
            this.RemoveStyle(this.GetStyle(name));
        }

        public bool RenameStyle(Style s, string newName)
        {
            Style style = (Style) this._styles[newName];
            if ((style != null) && (style != s))
            {
                return false;
            }
            this._styles.Remove(s.GetName());
            s._name = newName;
            this._styles.Add(newName, s);
            return true;
        }

        public virtual void Render(Style s, Graphics g, Rectangle r, string str, Image img, RenderFlags flags)
        {
            if (((flags & RenderFlags.Background) != RenderFlags.None) && ((bool) s.GetAttribute("Opaque")))
            {
                Brush brush = (Brush) s.GetAttribute("BackColor");
                if (brush != this._skipBrush)
                {
                    g.FillRectangle(brush, r);
                }
            }
            Margins attribute = (Margins) s.GetAttribute("Margins");
            r = InnerRect(r, attribute);
            Border border = (Border) s.GetAttribute("Border");
            if ((flags & RenderFlags.Border) != RenderFlags.None)
            {
                border.Render(g, r);
            }
            r = border.InnerRect(r);
            attribute = (Margins) s.GetAttribute("Padding");
            r = InnerRect(r, attribute);
            if ((flags & RenderFlags.Content) != RenderFlags.None)
            {
                this.RenderContent(s, g, r, str, img);
            }
        }

        public virtual void RenderContent(Style s, Graphics g, Rectangle r, string str, Image img)
        {
            if ((r.Width > 0) && (r.Height > 0))
            {
                bool flag = img != null;
                bool flag2 = (str != null) && (str.Length > 0);
                if (flag || flag2)
                {
                    if (flag)
                    {
                        this.RenderImage(s, g, r, img);
                    }
                    if (flag && flag2)
                    {
                        r = this.GetTextRectangle(s, r, img);
                    }
                    if (flag2)
                    {
                        this.RenderString(s, g, r, str);
                    }
                }
            }
        }

        public virtual void RenderImage(Style s, Graphics g, Rectangle r, Image img)
        {
            AlignImageEnum attribute = (AlignImageEnum) s.GetAttribute("AlignImage");
            switch (attribute)
            {
                case AlignImageEnum.Stretch:
                    this.DrawImage(g, img, r);
                    return;

                case AlignImageEnum.Hide:
                    return;
            }
            Rectangle rectangle = this.GetImageRectangle(s, r, img);
            if ((rectangle.Width > 0) && (rectangle.Height > 0))
            {
                if (attribute == AlignImageEnum.Scale)
                {
                    this.DrawImage(g, img, rectangle);
                }
                else
                {
                    Rectangle rsrc = new Rectangle(0, 0, rectangle.Width, rectangle.Height);
                    this.DrawImage(g, img, rectangle, rsrc);
                }
            }
        }

        public virtual void RenderString(Style s, Graphics g, Rectangle r, string str)
        {
            if (((str.Length != 0) && (r.Width > 0)) && (r.Height > 0))
            {
                Font attribute = (Font) s.GetAttribute("Font");
                Brush b = (Brush) s.GetAttribute("ForeColor");
                bool shortBox = r.Height <= attribute.Size;
                this.UpdateStringFormat(s, str, shortBox);
                TextEffectEnum enum2 = (TextEffectEnum) s.GetAttribute("TextEffect");
                if (enum2 != TextEffectEnum.Flat)
                {
                    int x = (enum2 == TextEffectEnum.Raised) ? 1 : -1;
                    Brush brush2 = (enum2 == TextEffectEnum.Raised) ? _shadowBrush : _lightBrush;
                    r.Offset(x, x);
                    this.DrawString(g, str, attribute, brush2, r, this._format);
                    r.Offset(-x, -x);
                }
                this.DrawString(g, str, attribute, b, r, this._format);
            }
        }

        public virtual void SetBaseAttributes()
        {
            Hashtable hashtable = this._baseStyle._atts;
            hashtable.Add("BackColor", SystemBrushes.Window);
            hashtable.Add("ForeColor", SystemBrushes.WindowText);
            hashtable.Add("Opaque", true);
            hashtable.Add("Font", _defaultFont);
            hashtable.Add("Trimming", StringTrimming.None);
            hashtable.Add("Wrap", true);
            hashtable.Add("Margins", new Margins(0, 0, 0, 0));
            hashtable.Add("Padding", new Margins(0, 0, 0, 0));
            hashtable.Add("Border", new Border());
            hashtable.Add("AlignHorz", AlignHorzEnum.General);
            hashtable.Add("AlignVert", AlignVertEnum.Top);
            hashtable.Add("TextEffect", TextEffectEnum.Flat);
            hashtable.Add("AlignImage", AlignImageEnum.LeftCenter);
            hashtable.Add("Spacing", 2);
        }

        private void SetFormatFlag(StringFormatFlags f, bool value)
        {
            if (value)
            {
                this._format.FormatFlags |= f;
            }
            else
            {
                this._format.FormatFlags &= ~f;
            }
        }

        public void SetSkipBrush(Brush brush)
        {
            this._skipBrush = brush;
        }

        protected virtual void UpdateStringFormat(Style s, string str, bool shortBox)
        {
            this.SetFormatFlag(StringFormatFlags.NoWrap, !((bool) s.GetAttribute("Wrap")));
            switch (((AlignHorzEnum) s.GetAttribute("AlignHorz")))
            {
                case AlignHorzEnum.General:
                    this._format.Alignment = this.GetGeneralAlignment(str);
                    break;

                case AlignHorzEnum.Near:
                    this._format.Alignment = StringAlignment.Near;
                    break;

                case AlignHorzEnum.Center:
                    this._format.Alignment = StringAlignment.Center;
                    break;

                case AlignHorzEnum.Far:
                    this._format.Alignment = StringAlignment.Far;
                    break;

                case AlignHorzEnum.Justify:
                    this._format.Alignment = StringAlignment.Near;
                    break;
            }
            if (shortBox)
            {
                this.SetFormatFlag(StringFormatFlags.NoClip, false);
                this._format.LineAlignment = StringAlignment.Near;
            }
            else
            {
                switch (((AlignVertEnum) s.GetAttribute("AlignVert")))
                {
                    case AlignVertEnum.Top:
                        this._format.LineAlignment = StringAlignment.Near;
                        return;

                    case AlignVertEnum.Center:
                        this._format.LineAlignment = StringAlignment.Center;
                        return;

                    case AlignVertEnum.Bottom:
                        this._format.LineAlignment = StringAlignment.Far;
                        return;
                }
            }
        }

        internal static Color ValidColor(Color clr)
        {
            if (clr.ToArgb() != 0)
            {
                return clr;
            }
            return Color.Black;
        }

        public Color TransparentColor
        {
            get
            {
                return this._transparentColor;
            }
            set
            {
                this._transparentColor = value;
            }
        }
    }
}

